package com.andnnl.template;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.ghost4j.GhostscriptLibrary.stdout_fn;

import com.andnnl.template.param.BaseParamConfig;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;

public class ParamTemplateManage {
    private static final int MAX_TEMP_LEN = 1000; // 模板变量部分最长长度
    private static final Map<Integer, List<ParamTemplate>> gwTempList = new ConcurrentHashMap<>();

    /**
     * 是否匹配模板
     *
     * @param msg
     * @param templPart
     * @return
     */
    private static List<Map<String, String>> matchTemplate(String msg, ParamTemplate paramTemplate) {
        String templPart[] = paramTemplate.getTemplatePart();
        List<String> paramList = paramTemplate.getParamNameList();
        Map<String, BaseParamConfig> paramMap = paramTemplate.getParamMap();

        List<Map<String, String>> resultList = new ArrayList<>();
        int fromIndex = 0;
        int msgLen = msg.length();

        for (int i = 0; i < templPart.length; i++) {
            if (i == 0) {
                if ("".equals(templPart[i]))
                    continue;
                if (msg.startsWith(templPart[i])) {
                    fromIndex = templPart[i].length();
                    continue;
                } else {
                    // 大部分的模板与该短信开头就已经不一样，并在这里返回
                    return null;
                }
            }
            // if ("".equals(templPart[i]))
            // continue;
            // 模板以变量结尾，判断null即可
            String paramName = paramList.get(i - 1);
            if ("".equals(templPart[i])) {
                int tempLen = msgLen - fromIndex; // 变量部分字符长度
                if (tempLen > MAX_TEMP_LEN) {
                    // 超过变量长度允许最大值，视为不符合模板
                    return null;
                }
                String val = msg.substring(fromIndex, msgLen);
                if (!paramMap.get(paramName).validateValue(val)) {
                    System.out.println("参数值不符合模板要求:" + paramName + ":" + val);
                    return null;
                }
                resultList.add(Collections.singletonMap(paramName, val));
                return resultList;
            }
            int pos = msg.indexOf(templPart[i], fromIndex);
            if (pos < 0) {
                // 不匹配，不符合模板
                return null;
            } else {
                int tempLen = pos - fromIndex; // 变量部分字符长度
                if (tempLen > MAX_TEMP_LEN) {
                    return null;// 超过变量长度允许最大值，视为不符合模板
                }
                String val = msg.substring(fromIndex, pos);
                if (!paramMap.get(paramName).validateValue(val)) {
                    System.out.println("参数值不符合模板要求:" + paramName + ":" + val);
                    return null;
                }
                resultList.add(Collections.singletonMap(paramName, val));
                fromIndex = pos + templPart[i].length();
            }
        }
        // 最后判断最后的开始索引为消息长度为匹配成功
        if (msgLen == fromIndex) {
            return resultList;
        }
        return null;
    }

    // 解析模板
    public static ParamTemplate validateTemplate(String template, String jsonConfig) {

        // Map<String, String> valueCache = new HashMap<>(); // 参数值缓存
        try {
            // 解析JSON配置
            ObjectMapper mapper = new ObjectMapper();
            JsonNode rootNode = mapper.readTree(jsonConfig);
            Map<String, BaseParamConfig> paramMap = new HashMap<>();
            List<String> paramNameList = new ArrayList<>();
            // 解析每个参数
            for (JsonNode paramNode : rootNode.path("parameters")) {
                String type = paramNode.path("type").asText("string");
                BaseParamConfig config;

                config = ParamConfigFactory.create(type);
                config.fromJson(paramNode);

                config.setName(paramNode.path("name").asText());
                config.validate();
                paramMap.put(config.getName(), config);
            }

            // 替换模板中的占位符
            Pattern pattern = Pattern.compile("\\$\\{(\\w+)\\}");
            Matcher matcher = pattern.matcher(template);

            while (matcher.find()) {
                String paramName = matcher.group(1);
                paramNameList.add(paramName);
                BaseParamConfig config = paramMap.get(paramName);
                if (config == null) {
                    throw new IllegalArgumentException("模板参数未定义: " + paramName);
                }
            }
            // 使用正则表达式分割模板，获取参数间的静态文本部分
            String[] templatePart = pattern.split(template, -1); // -1保留末尾空字符串
            // 判断是否有连续的参数，即templatePart中有空字符串的，就抛出异常，不包括最后一个
            if (templatePart.length > 1) {
                for (int i = 1; i < templatePart.length - 2; i++) {
                    if (templatePart[i].isEmpty()) {
                        throw new IllegalArgumentException("模板参数连续: " + templatePart[i]);
                    }
                }
            }
            return new ParamTemplate(template, jsonConfig, paramNameList, paramMap, templatePart);
        } catch (Exception e) {
            // 处理异常，例如记录日志
            System.err.println("模板验证失败: " + e.getMessage());
            // throw new IllegalArgumentException("ERROR: " + e.getMessage());
            return null;
        }
    }

    // ============ 测试用例 ============
    public static ParamTemplate matchGwTemp(int gwNum, String msg) {
        for (ParamTemplate temp : gwTempList.get(gwNum)) {
            List<Map<String, String>> rs = matchTemplate(msg, temp);
            if (rs != null) {
                System.out.println("参数值：" + JSONUtil.toJsonStr(rs));
                return temp;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        testValidConfigurations();
        testInvalidConfigurations();
        testValueCache();
        // testFileLoading();
    }

    static void testValidConfigurations() {
        System.out.println("===== 有效配置测试 =====");
        int gwNum = 10000;

        // 测试1: 基础类型
        String template = "订单号：${orderId}，产品：${product}，数量：${quantity}，价格：${price}";
        String jsonConfig = "{ \"parameters\": [" +
                "{ \"name\": \"orderId\", \"type\": \"string\", \"minLength\": 8, \"maxLength\": 8 }," +
                "{ \"name\": \"product\", \"type\": \"enum\", \"options\": [\"手机\", \"笔记本\", \"平板\"] }," +
                "{ \"name\": \"quantity\", \"type\": \"int\", \"minValue\": 1, \"maxValue\": 5 }," +
                "{ \"name\": \"price\", \"type\": \"double\", \"minValue\": 50, \"maxValue\": 200 }" +
                "]}";

        ParamTemplate result = validateTemplate(template, jsonConfig);
        addTemp(gwNum, result);

        // 测试2: 日期类型
        String dateTemplate = "开始日期：${start}，结束日期：${end}";
        String dateConfig = "{ \"parameters\": [" +
                "{ \"name\": \"start\", \"type\": \"date\", \"minDate\": \"2023-01-01\", \"maxDate\": \"2023-01-31\", \"format\": \"MM/dd/yyyy\" },"
                +
                "{ \"name\": \"end\", \"type\": \"date\", \"minDate\": 1677628800000, \"maxDate\": 1680288000000 }" +
                "]}";
        ParamTemplate resultDate = validateTemplate(dateTemplate, dateConfig);
        addTemp(gwNum, resultDate);

        // 测试3: 正则表达式约束
        String regexTemplate = "${username}$用户名：，邮箱：${email}";
        String regexConfig = "{ \"parameters\": [" +
                "{ \"name\": \"username\", \"type\": \"regex\", \"regex\": \"[a-z0-9_-]{3,15}\" }," +
                "{ \"name\": \"email\", \"type\": \"regex\", \"regex\": \"[\\\\w-]+(\\\\.[\\\\w-]+)*\\\\@[\\\\w-]+(\\\\.[\\\\w-]+)+\", \"minLength\": 5, \"maxLength\": 30 ,\"includes\":[\"@\",\"w\"],\"excludes\":[\"s\",\"x\"]}"
                +
                "]}";
        ParamTemplate resultRegex = validateTemplate(regexTemplate, regexConfig);
        addTemp(gwNum, result);

        System.out.println("基础类型测试: " + result);
        printResult(result);
        System.out.println("日期类型测试: " + resultDate);
        printResult(resultDate);
        System.out.println("正则表达式测试: " + resultRegex);
        printResult(resultRegex);

        for (ParamTemplate temp2 : gwTempList.get(gwNum)) {
            String msg = temp2.genMsg();
            System.out.println("原始内容: " + msg);
            ParamTemplate matchGwTemp = matchGwTemp(gwNum, msg);
            System.out.println("是否匹配: " + (matchGwTemp!=null));
            System.out.println();
        }

    }

    private static void addTemp(int gwNum, ParamTemplate result) {
        if (result == null) {
            return;
        }
        gwTempList.computeIfAbsent(gwNum, k -> new ArrayList<>()).add(result);
    }

    private static void printResult(ParamTemplate result) {
        if (result != null) {
            System.out.println("template: " + result.getTemplate());
            System.out
                    .println("getTemplatePart: " + JSONUtil.toJsonStr(result.getTemplatePart()));
            String msg = result.genMsg();
            System.out.println("生成测试内容: " + msg);
            try {
                System.out.println("验证生成的内容：" + matchTemplate(msg, result));
            } catch (Exception e) {
                System.out.println("验证生成的内容：" + e.getMessage());
            }
        }
        System.out.println();
    }

    static void testInvalidConfigurations() {
        System.out.println("\n===== 无效配置测试 =====");

        // 测试1: 无效长度范围
        String invalid1 = "{ \"parameters\": [" +
                "{ \"name\": \"test\", \"type\": \"string\", \"minLength\": 10, \"maxLength\": 5 }" +
                "]}";
        System.out.println("无效长度: " + validateTemplate("${test}", invalid1));

        // 测试2: 无效数值范围
        String invalid2 = "{ \"parameters\": [" +
                "{ \"name\": \"test\", \"type\": \"int\", \"minValue\": 100, \"maxValue\": 50 }" +
                "]}";
        System.out.println("无效数值范围: " + validateTemplate("${test}", invalid2));

        // 测试3: 缺失枚举选项
        String invalid3 = "{ \"parameters\": [" +
                "{ \"name\": \"test\", \"type\": \"enum\" }" +
                "]}";
        System.out.println("缺失枚举: " + validateTemplate("${test}", invalid3));
    }

    static void testValueCache() {
        System.out.println("\n===== 缓存机制测试 =====");

        String template = "ID: ${id}, 副本: ${id}";
        String config = "{ \"parameters\": [" +
                "{ \"name\": \"id\", \"type\": \"int\", \"minValue\": 1, \"maxValue\": 1 }" +
                "]}";

        // 应生成相同的ID值
        System.out.println("缓存一致性: " + validateTemplate(template, config));
    }
    /*
     * static void testFileLoading() {
     * System.out.println("\n===== 文件加载测试 =====");
     * 
     * try {
     * // 创建临时配置文件
     * File temp = File.createTempFile("config", ".json");
     * String configContent = "{ \"parameters\": [" +
     * "{ \"name\": \"fileTest\", \"type\": \"enum\", \"options\": [\"成功!\"] }" +
     * "]}";
     * new java.io.FileWriter(temp).append(configContent).close();
     * 
     * System.out.println("文件加载: " +
     * generateContentFromFile("测试结果: ${fileTest}", temp.getAbsolutePath()));
     * 
     * // 测试缓存
     * System.out.println("文件缓存: " +
     * generateContentFromFile("再次测试: ${fileTest}", temp.getAbsolutePath()));
     * 
     * } catch (Exception e) {
     * System.out.println("文件测试失败: " + e.getMessage());
     * }
     * }
     */
}